package com.geekydoo.commands;

import generated.TaskType;

import java.util.List;
import java.util.logging.Logger;

import com.geekydoo.CommandParser;
import com.geekydoo.CommandParser.CommandTypes;
import com.geekydoo.GeekyDooException;
import com.geekydoo.InputOutputHandler;

/**
 * The purpose of this class is provide help for each command supported by the
 * program.
 * 
 * @author Patrick Dutch
 * 
 */
public class HelpCommand implements Command {

	private static Logger logger = Logger.getLogger("geekydoo");

	// The list of all task objects managed by the program
	private List<TaskType> taskList;

	// Error messages printed by the help command
	private static final String ERROR_UNEXPECTED = "Unexpected error in the program!";

	// Non-detailed help message
	private static final String HELPMSG_GENERAL = "Valid commands are: add, delete, edit, open, search, "
			+ "\n\t                    clear, display, help, undo, exit";

	// Prompts printed by the help command
	private static final String PROMPT_DETAILED_HELP = "Which command would you like help with? (blank to cancel): ";

	// Command-specific help messages
	private static final String HELPMSG_SPECIFIC_ADD =
			"Command aliases: new, create"
					+ "\n\tDescription: "
					+ "\n\t  The add command allows you to add new tasks to your list of tasks."
					+ "\n\t  This is accomplished through asking you to provide each task attribute. "
					+ "\n\t  Only attributes marked with (*) are required to be filled in."
					+ "\n\t  For non-required attributes, you can simply press 'enter' to leave that attribute blank."
					+ "\n\tAttributes: "
					+ "\n\t  1) Title - The title can be anything you like, but it cannot be left empty."
					+ "\n\t  2) Date - The program allows dates up to 2099. You can input your dates with the following characters"
					+ "\n\t            separating the parts: /- . so, for example, 30/12 2012 and 15-11.2015 all work. If you don't"
					+ "\n\t            specify a year then the program assumes the current year. The format is day followed by month."
					+ "\n\t  3) Time - Dates should be entered in the format HH:MM or H:MM. This program uses a 24-hour clock so"
					+ "\n\t            allowed times range from 0:00 to 23:59."
					+ "\n\t  4) Categories - Categories can help you group similar tasks together for easy reference later. You can"
					+ "\n\t                  assign as many categories to a task as you want, separating them with commas."
					+ "\n\t  5) Description - This attribute is for storing any notes along with the task so you can refer to"
					+ "\n\t                   them later."
					+ "\n\t  6) Document links - Here you can store addresses of files, websites, or email addresses associated"
					+ "\n\t                      with a task. Later you can use the 'open' command to open these links."
					+ "\n\t                      Example 1) Enter http://download.oracle.com/javase/tutorial/java/nutsandbolts/while.html"
					+ "\n\t                                 to save a link to this webpage for opening later."
					+ "\n\t                      Example 2) Enter joesmoe@company.com to save Joe's email address and have your default"
					+ "\n\t                                 mail client compose an email to Joe when you open this link."
					+ "\n\t                      Example 3) Enter C:\\Users\\Joey\\document.doc to save a link to this word document"
					+ "\n\t                                 and have it open in MS Word when you use the 'open' command.";
	private static final String HELPMSG_SPECIFIC_DISPLAY =
			"Command aliases: show"
					+ "\n\tDescription: "
					+ "\n\t  The display command allows you to display the information of all tasks matching your provided"
					+ "\n\t  date, time, or list of categories, or to simply display all tasks. To display all tasks, you should"
					+ "\n\t  enter a blank line when prompted to enter a criterion to display by."
					+ "\n\tDisplay criteria: "
					+ "\n\t  1) Date - Enter any valid date and the task information for all tasks falling on this date will be shown."
					+ "\n\t            Example: 15-12 to display all tasks occurring on December 15th of the current year or 28/2/2012"
					+ "\n\t                     to display all tasks occurring on February 28th, 2012."
					+ "\n\t  2) Time - Enter any valid time and the task information for all tasks occurring at this time will be shown."
					+ "\n\t  3) Categories - Enter a list of categories separated by commas and all tasks matching the entire list you"
					+ "\n\t                  entered will be shown. Example: 'important, homework' matches tasks with both the category"
					+ "\n\t                  'important' and the category 'homework' in their categories attribute.";
	private static final String HELPMSG_SPECIFIC_DELETE =
			"Command aliases: remove, erase"
					+ "\n\tDescription: "
					+ "\n\t  The delete command allows you to delete tasks that you no longer need access to. To delete a task, simply"
					+ "\n\t  enter its task number when prompted and then confirm your decision.";
	private static final String HELPMSG_SPECIFIC_CLEAR =
			"Description: "
					+ "\n\t  The clear command allows you to clear your entire task list. This means that all of your current tasks will"
					+ "\n\t  no longer be accessible. To clear your task list, just confirm your decision when prompted.";
	private static final String HELPMSG_SPECIFIC_EDIT =
			"Command aliases: modify, change"
					+ "\n\tDescription: "
					+ "\n\t  The edit command allows you to change any attributes of a task. After executing the edit command, you"
					+ "\n\t  will be prompted for the task number. After giving the task number, you will be prompted for a list of"
					+ "\n\t  attributes that you would like to edit. The attributes are title, date, time, category, description, and link."
					+ "\n\t  You should separate attributes in your list with a space, so, for example, entering 'date, link' will allow"
					+ "\n\t  you to edit the date and document links of a task."
					+ "\n\tNotes: "
					+ "\n\t  1) If you wish to remove an optional attribute like time, categories, or description, you can simply enter a blank"
					+ "\n\t     when prompted for the new value of these attributes."
					+ "\n\t  2) When editing the document links, you edit a specific link by entering its link number, which will be shown to you."
					+ "\n\t     You can also add a new link to a task by typing 'new' when prompted for the link number to edit."
					+ "\n\t     Additionally, you can remove a document link by choosing its link number and entering a blank when prompted for"
					+ "\n\t     what the new link should be.";
	private static final String HELPMSG_SPECIFIC_SEARCH =
			"Command aliases: find, seek"
					+ "\n\tDescription: "
					+ "\n\t  The search command simply looks for matches among the tasks of the words you enter when prompted."
					+ "\n\t  The attributes searched for matches are the title, the categories, the description, and the document links."
					+ "\n\t  Example: If you enter 'what where' then all tasks containing either the word 'what' or the word 'where'"
					+ "\n\t           will be displayed to you, as well as any tasks containing both words.";
	private static final String HELPMSG_SPECIFIC_OPEN =
			"Description: "
					+ "\n\t  The open command allows you to open the links you've associated with a task. The types of links you"
					+ "\n\t  can open include any file or folder on your computer, weblinks, and email addresses. More information"
					+ "\n\t  can be found about adding different links in the help section for the 'add' command."
					+ "\n\t  After executing the 'open' command and entering the task number of the task whose links you'd like to"
					+ "\n\t  open, you'll be presented with a list of associated links. You can open a link by entering its link"
					+ "\n\t  number, which will be shown to you. You can also open all links by entering 'all' as the link number, or"
					+ "\n\t  you can decide to not open any links by entering a blank at the prompt.";
	private static final String HELPMSG_SPECIFIC_UNDO =
			"Description: "
					+ "\n\t  The undo command undoes the last command you executed that changed something about the task list. Commands that"
					+ "\n\t  you can undo are add, clear, delete, edit, and undo. The undo command functions like a toggle, meaning that"
					+ "\n\t  if you execute an undo command after executing an undo command, the resulting task list will be the one that you had"
					+ "\n\t  before you executed the previous undo command.";
	private static final String HELPMSG_SPECIFIC_EXIT =
			"Command aliases: quit, stop, bye"
					+ "\n\tDescription: "
					+ "\n\t  The exit command ends your current GeekyDoo session and exits the program. Your task list will still be there"
					+ "\n\t  when you run GeekyDoo again.";
	private static final String HELPMSG_SPECIFIC_HELP =
			"Description: "
					+ "\n\t  The help command displays the list of valid commands and asks whether you would like to see more information about"
					+ "\n\t  any particular command. If so, enter that command's name. If not, enter blank to exit the help command.";
	private static final String HELPMSG_SPECIFIC_INVALID =
			"Command not recognized. Please enter a valid command name (listed above) if you"
					+ "\n\twould like to know more about a specific command.";

	// A descriptive name for the empty string
	private static final String EMPTY_STRING = "";

	public void execute(List<TaskType> tasks) throws GeekyDooException {
		taskList = tasks;

		InputOutputHandler.printToConsole(HELPMSG_GENERAL, true, false);
		String response = InputOutputHandler.getInputFromConsole(PROMPT_DETAILED_HELP, true);
		if (response.equals(EMPTY_STRING)) {
			return;
		}

		CommandTypes commandToHelp = CommandParser.getCommandParser().convertStringToCommandType(response);
		switch (commandToHelp) {
			case ADD:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_ADD, true, false);
				break;
			case DISPLAY:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_DISPLAY, true, false);
				break;
			case DELETE:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_DELETE, true, false);
				break;
			case CLEAR:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_CLEAR, true, false);
				break;
			case EDIT:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_EDIT, true, false);
				break;
			case SEARCH:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_SEARCH, true, false);
				break;
			case OPEN:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_OPEN, true, false);
				break;
			case UNDO:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_UNDO, true, false);
				break;
			case EXIT:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_EXIT, true, false);
				break;
			case HELP:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_HELP, true, false);
				break;
			case INVALID:
				InputOutputHandler.printToConsole(HELPMSG_SPECIFIC_INVALID, true, false);
				break;
			default:
				logger.severe("Execution reached a point it shouldn't reach, check logic in CommandParser!");
				assert (false);
				throw new Error(ERROR_UNEXPECTED);
		}
	}

	public boolean isListModified() {
		return false;
	}

	public List<TaskType> getPreExecutionList() {
		return taskList;
	}

}
